/*====================================================================================
# «ДЭНСИ:РМК» module of «ДЭНСИ: КАССА» complex is the front-office application for POS-systems based on fiscal registrators.
# © OOO "DNC Trade" 2009, Authors: Savitskaya Alexandra, Pavlova Irina(Pavlova_Irina@shtrih-s.ru), Sukhanova Anna (anuta.s13@gmail.com), Savrasov Alexandr.
# This is a FREE software, licensed under GNU/GPL terms. See details in LICENSING_ENG.TXT in main directory
#====================================================================================
# Модуль «ДЭНСИ:РМК» программного комплекса «ДЭНСИ: КАССА» - рабочее место кассира для POS-систем на базе фискальных регистраторов
# © ООО "ДЭНСИ Трейд" 2009, Авторы: Савицкая Александра, Павлова Ирина(Pavlova_Irina@shtrih-s.ru), Суханова Анна (anuta.s13@gmail.com), Саврасов Александр.
# Данная программа является свободным программным обеспечением, выпускается на условиях Стандартной Общественной Лицензии GNU/GPL
# Подробнее смотрите в файле LICENSING_RUS.TXT в основной директории
#====================================================================================*/
#include "reg_pgsql.h"


//#include <qdatetime.h>
#include <math.h>
#include <stdlib.h>
#include "addon_func.h"

#define ORDERBYCODE "w.internal_id"    // 0
#define ORDERBYBARCODE "wb.barcode" //1
#define ORDERBYTITLE "w.longtitle"         //2

//==================================================================================//
Registration::Registration()
{
    //puts("Registration:: Registration()");
    Set_Db("LinCash");
}

//==================================================================================//
Registration::Registration(SP * sparam, const char * conf_path) : PGSQL(conf_path)
{
    sp = sparam;
    log->PrintString(log_type, INFO, "Registration::Registration - Connect to db parameters form path = %s \n", conf_path);
}

//==================================================================================//
Registration::Registration(const char *dbname, const char *user, const char *password, const char *host, const char *hostaddr, const char *port, const char* log_path, SP * sparam) : PGSQL(dbname, user, password, host, hostaddr, port, log_path)
{
    log->PrintString(log_type, INFO, "AccessRights::AccessRights - Connect to db with  parameters : dbname = <%s>, user = <%s>, password = <%s>, host = <%s>, hostaddr = <%s>, port = <%s>, log_path = <%s>)\n", dbname, user, password, host, hostaddr, port, log_path);
    //printf("Registration::Registration(dbname = <%s>, user = <%s>, password = <%s>, host = <%s>, hostaddr = <%s>, port = <%s>, log_path = <%s>)\n", dbname, user, password, host, hostaddr, port, log_path);
    sp = sparam;
}

//==================================================================================//
Registration::~Registration() 
{
    //puts("Registration::~Registration()");
    //close(log);
    //Close_Connection();
}

//==================================================================================//
// weit - параметр содержит флаг дробного количества: 0 - штучный товар, 1 - весовой товар
//max_quantity - содержит максимальное количество товара, если требуется контроль количества(не разрешиены отрицательные остатки), либо -1 в противном случае.
//returns:
//0 - все нормально
//4 - не верный код товара
//7 - запрос в БД не был выполнен, смотреть логфайл
int Registration::Get_Max_Quantity(const char * int_code, int & weit, double & max_quantity)
{
//puts("int Registration::Get_Max_Quantity(const char * int_code, int & weit, double & max_quantity)");
  int er = Internal_Get_Product(int_code);
  if(er > 0) return er;
  
  int flags = atoi(PQgetvalue(result, 0, 8));
  
  weit = flags & ALLOWFRACTIONAL;
 
  if((flags & ALLOWNEGATIVEQUANTTITY) == ALLOWNEGATIVEQUANTTITY)
    max_quantity = -1;
  else
    max_quantity = atof(PQgetvalue(result, 0, 3));
  return 0;
}
 
 
//==================================================================================//
//code - код товара (внутренний или штрих-)
//q - количество товара
//rec - указатель на структуру чека
//fl : true - использовать штрих-код товара, false - исрпользовать внутренний код товара // этот параметр не нужен - у товара всегда есть внутренний код
//returns : 
//0 - все нормально
//5 - нет требуемого количества товара
//7 - запрос в БД не был выполнен, смотреть логфайл
//8 - попытка продать штучный товар как весосой    
int Registration::Quantity_Control(const char *code, double q/*, bool fl*/)
{
//puts("Registration::Quantity_Control(const char *code, double q)");
  int er;
/*  if(fl) er = Bar_Get_Product(code);
  else */
  er = Internal_Get_Product(code);
  if(er > 0) return er;

  er = Check_Product_Atr(q, false);
  if(er > 0) return er;
 
  return 0;
}

//==================================================================================//
int Registration::Get_Pattern_Param(const char *code, double *quantity, char *internal_code)
{
   //puts("int Registration::Get_Pattern_Param(const char *code, double *quantity, char *internal_code)");
   
   char *prefix = (char *) calloc(3, sizeof(char));
   if ( prefix == NULL ) printf("NULL CALLOC!!! parameter prefix\n");
   *prefix = *code;
   *(prefix + 1) = *(code + 1);
   /*puts("***************************************************************");
   printf("prefix = %s \n", prefix);*/
   if ( (*prefix<'0') || (*prefix> '9' ) || (*(prefix+1) <'0') || (*(prefix+1) > '9')  )  {   free(prefix);  return 1;   }
   /*
   puts("***************************************************************");
   printf("prefix = %s \n", prefix);
  puts("***************************************************************");
   */
   
   int res = Query_Pattern(prefix);
   free(prefix);
   
   //printf("res = %d \n", res);
   int ret = 0;
   
   if ( res != 2 ) return 7; 	// Невыполнен запрос в базу, нет коннекта


   int n = PQntuples(result);
   if ( n <= 0 )  return 1; 	//Нет шаблона с таким префиксом
   
   
   int len = PQgetlength(result, 0, 0);
   //Неверная длина весового штрих-кода для префикса штрих-кода
   //if ( len == 26 ) len = 13;
   if((len != (int) strlen(code)) && ((int)len/2 != (int) strlen(code))) return 2; 

   char * pattern = (char *) calloc(len + 2, sizeof(char));
   if(pattern == NULL) printf("NULL CALLOC!!! parameter pattern\n");
   strcpy(pattern, PQgetvalue(result, 0, 0));
   double multiplier = atof(PQgetvalue(result, 0, 1));
   PQclear(result);
   
   char* tmp = (char*) calloc(len+2, sizeof(char));
   if (len == 26) {
	for (int k=0; k<13; k++) *(tmp+k) = *(pattern+2*k+1);	
   } else strcpy(tmp, pattern);
   free(pattern); 

   char * copy = (char *) calloc(strlen(code) + 1, sizeof(char));
   if(copy == NULL) printf("NULL CALLOC!!! parameter copy\n");
   strcpy(copy, code);
   int i = 0;
   int j = 0;
   char ch;
   bool code_fl = false;
   bool quant_fl = false;

   while ( j != -1 )        {
	//printf("while j = %d, i = %d, ch = %d\n", j, i, ch);
	if (i == 0) ch = *(tmp + j);
	if ((j == len - 1) || (ch != *(tmp + j + 1)))  {
		//printf("*(tmp + j + 1) code = %d \n", tmp[j+1]);
		int l = strlen(copy);
		//printf("strlen(copy) = %d\n", l);
		//printf("copy - <%s>\n", copy);
		//printf("ch code = %d \n", ch);
     
		switch(ch)  {
			   //  case 'K' :
			case -102 :   {
			       //printf("case K\n");

			       //printf("2  case K\n");
			       for(int k = 0; k < i + 1; k ++) *(internal_code + k) = *(copy + k);
			       //   strncpy(*internal_code, copy, i + 1);
			       //printf("internal_code after strncpy <%s>, adress [%p]\n", internal_code, internal_code);
			       free(copy);
			       copy = (char*) calloc(l - i + 1, sizeof(char));
			       if(copy == NULL) printf("NULL CALLOC!!! parameter copy\n");
			       for(int k = 0; k < l - i + 1; k++) *(copy + k) = *(code + j + 1 + k);
			       code_fl = true;
			       i = 0;
			       break;
			}
			   //  case 'M' :
		       case -100 :   {
			       //printf("case M\n");

			       char * q_str = (char *) calloc(i + 1, sizeof(char));
			       if(q_str == NULL) printf("NULL CALLOC!!! parameter q_str\n");
			       //strncpy(q_str, copy, i + 2);
			       for(int k = 0; k < i + 1; k++) *(q_str + k) = *(copy + k);
			       //printf("q_str after strncpy <%s>\n", q_str);
			       *quantity = atof(q_str) * multiplier;
			       free(q_str);
			       free(copy);
			       copy = (char*) calloc(l - i, sizeof(char));
			       if(copy == NULL) printf("NULL CALLOC!!! parameter copy\n");
			       for(int k = 0; k < l - i; k++) *(copy + k) = *(code + j  +  1 + k);
			       quant_fl = true;
			       i = 0;
			       break;
			   }
			   // case 'H' :
		       case -99 :   {
			       //printf("case H\n");
			       free(copy);
			       copy = (char*) calloc(l - i, sizeof(char));
			       if(copy == NULL) printf("NULL CALLOC!!! parameter copy\n");
			       //printf("len of copy %d\n", l - i);
			       for(int k = 0; k < l - i; k++) *(copy + k) = *(code + j + 1 + k);
			       i = 0;
			       break;
			}
			default:   {
				free(copy);
				free(tmp);
				return 1;		
			}
		}			
	}   else i++;
	j++;
	if(code_fl && quant_fl) j = -1;
   }
   free(copy);
   free(tmp);
   
   //if(ret == 0) printf("internal_code in the end of Get_Pattern_Param(...) <%s>, adress [%p]\n", internal_code, internal_code);
   
   return ret;
}

//==================================================================================//
//code - код товара (внутренний или штрих-)
//q - количество товара
//rec - указатель на структуру чека
//code_fl : true - использовать штрих-код товара, false - исрпользовать внутренний код товара
//return_fl : true - производится возврат товара
//copy_fl : true - производится подбор для копии чека
//npos : позиция чека, в которую будет добавлен товар
//returns : 
//0 - все нормально
//1 - продажа данного товара запрещена в карточке товара
//2 - возврат данного товара запрещен в карточке товара
//3 - не верный штрих-код товара 
//4 - не верный код товара
//5 - нет требуемого количества товара
//6 - не верное имя товара в БД 
//7 - запрос в БД не был выполнен, смотреть логфайл
//8 - попытка продать штучный товар как весосой
//9 - истек срок годности
//10 - переполнение при умножении
//11 - переполнение при сложении
//12 - не верный весовой штрих-код товара, товар с указанным кодом не найден
int Registration::New_Receipt_Record(const char *code, double q, Receipt *rec, bool code_fl, bool return_fl, bool copy_fl, int &npos)
{
    //puts("Registration::New_Receipt_Record(char *code, double q, Receipt *rec, bool code_fl, bool return_fl, bool copy_fl, int &npos)");
	//printf("New_Receipt_Record (code = %s, q = %f, code_fl = %d, return_fl = %d, copy_fl = %d) \n", code, q, code_fl, return_fl, copy_fl);

	printf("Add position ( (bar)code = %s, quantity = %f ) ", code, q);
	int er = 0;
	int pattern_er = 0;

	char *internal_code = NULL;

	//printf("q == %f \n", q);

	if (rec->GetStateofClosing())
		rec->Clear_Receipt();
	/********************************************///
	// Ищем по штрих-коду
	if (code_fl) {
		//printf("barcode = %s \n", code);
		/* определяет шк, код цену количество, срок годности название флаги группы схемы коэффициенты*/
		er = Bar_Get_Product(code);
		if (er != 3) {
			internal_code = (char*) calloc(PQgetlength(result, 0, 1) + 1,
					sizeof(char));
			strcpy(internal_code, PQgetvalue(result, 0, 1));
		}
		if (er == 3) {
			// Указанный штрих-код не найден,
			// Поищем в весовых штрих-кодах
			double quantity;
			internal_code = (char*) calloc(strlen(code) + 1, sizeof(char));
			pattern_er = Get_Pattern_Param(code, &quantity, internal_code); // выделяет внутрений код товара и его количество из весового шк
			int k = 0;

			int internal_code_by_int = atoi(internal_code);
			strcpy(internal_code, "");

			itoa(internal_code_by_int, internal_code);
			//printf("Get_Pattern_Param(weight code = %s , &quantity = %f, internal_code = %s) = %d\n", code, quantity, internal_code, pattern_er);
			if (pattern_er == 0) {
				q = quantity;
				er = Internal_Get_Product(internal_code); /* определяет параметры товара по его вн. коду*/
				//if(er == 4) er = 12;
			} else if (pattern_er == 7)
				er = 7;

		}
	} else {
		//printf("code = %s \n", code);
		internal_code = (char *) calloc(strlen(code) + 1, sizeof(char));
		strcpy(internal_code, code);
		// Поиск по внутреннему коду
		er = Internal_Get_Product(internal_code); /* определяет параметры товара по его вн. коду*/

	}
	/********************************************///

	if (er != 0)
		return er;

	printf("internal_code = %s \n", internal_code);

	Get_Check_Position(internal_code, false, npos, rec); // определяет номер позиции в чеке куда добавить новую позицию
	//printf("code = %s npos = %d q = %f \n ", internal_code, npos, q);

	//er = 0;
	//если не копия чека и не возврат
	//if ( !copy_fl && !return_fl )    {
	if (!copy_fl) {
		// q =  при не объединении строк, нужно посчитать количество товара с таким кодом
		double tmp = 0;
		//if ( (sp->association_positions == NOTASSOCIATION) && !return_fl && !copy_fl ) tmp = rec->QuantityWareByCode(code, true);
		tmp = rec->QuantityWareByCode(internal_code, true);
		//printf("QuantityWareByCode(internal_code = %s) = %f \n", internal_code, tmp);

		double coef = atof(PQgetvalue(result, 0, 12));
		if (coef == 0)
			coef = 1;

		if (copy_fl || return_fl) {
			coef = 1;
		} // поскольку из транзакций считывается кол-во уже с учетом коэффициента
		//printf("coef = %f \n", coef);

		if (npos != -1) {
			int quantity_npos = rec->GetPosElemRef(npos)->GetQuantity();
			//printf("quantity_npos = %f \n", quantity_npos);
			//printf("Check_Product_Atr(q + quantity_npos = %f)\n", q + quantity_npos);
			er = Check_Product_Atr(q * coef + quantity_npos, return_fl); // проверят возможность продажи товара по флагам
		} else {
			//printf("Check_Product_Atr(q + tmp = %f)\n", q + tmp);
			er = Check_Product_Atr(q * coef + tmp, return_fl); // проверят возможнось продажи товара по флагам
		}
	}

	if (internal_code != NULL)
		free(internal_code);

	/* добавление позиции в чек */
	if (er == 0) {
		if (npos == -1) {
			er = Overflow_Control(rec->GetResultSum(), q
					* atof(PQgetvalue(result, 0, 2)), 0);
			if (er == 0) {
				//printf("q = %f \n", q);
				//printf("1 coeff == %f \n", coef);
				double coef = atof(PQgetvalue(result, 0, 12));
				if (coef == 0)
					coef = 1;
				if (copy_fl || return_fl) {
					coef = 1;
				} // поскольку из транзакций считывается кол-во уже с учетом коэффициента

				rec->Add_Record(PQgetvalue(result, 0, 0)/*barcode*/,
						PQgetvalue(result, 0, 1)/*internal code*/, PQgetvalue(
								result, 0, 6)/*shortcut*/, PQgetvalue(result,
								0, 7)/*longtitle*/,
						q * coef /*quantity x coefficient*/, atof(PQgetvalue(
								result, 0, 2))/*price*/, atoi(PQgetvalue(
								result, 0, 8))/*flags*/, !code_fl/*code_flag*/,
						atoi(PQgetvalue(result, 0, 10))/*auto_scheme*/, atoi(
								PQgetvalue(result, 0, 11))/*fix_scheme*/, atoi(
								PQgetvalue(result, 0, 9))/*tax_group*/, atof(
								PQgetvalue(result, 0, 4))/*min_price*/, atoi(PQgetvalue(result, 0, 13)) /*operator_id*/,
								PQgetvalue(result, 0, 14)/*account*/, atof(PQgetvalue(result, 0, 15)) /*fee*/);
			}
			PQclear(result);
			//Add_Taxes(rec);
			npos = rec->record_num - 1;
		} else {
			double coef = atof(PQgetvalue(result, 0, 12));
			if (coef == 0)
				coef = 1;
			q = coef * q;
			PQclear(result);
			//printf("rec->GetPosElemRef(npos)->GetQuantity() = %f \n", rec->GetPosElemRef(npos)->GetQuantity());
			//printf("q = %f \n", q);
			if ((er = Overflow_Control(rec->GetResultSum(),
					(rec->GetPosElemRef(npos)->GetQuantity() + q) * rec->GetPosElemRef(npos)->GetPrice(),
					rec->GetPosElemRef(npos)->GetSum())) == 0) {
				rec->GetPosElemRef(npos)->SetQuantity(rec->GetPosElemRef(npos)->GetQuantity() + q);
			}
		}
	}

	/********************************************/
	return er;
}

//==================================================================================//
//7 - запрос в БД не был выполнен, смотреть логфайл
int Registration::Add_Taxes(Receipt *rec, int npos)
{

    int ret = 0;
    int n = 0;
    
    if (rec->GetPosElemRef(npos)->tax_group != 0)  {
	char * taxgr_str = NULL;
	taxgr_str = itoa(rec->GetPosElemRef(npos)->tax_group);
	if ( taxgr_str == NULL ) log->PrintString(log_type, ERROR, "Registration::Add_Taxes - Error of convert from integer = %d to char* = NULL \n", rec->GetPosElemRef(npos)->tax_group);

	int res = Query_Taxes(taxgr_str); //trg.tax_rate_id - 0, trg.base_flag - 1, tr.longtitle - 2, tr.shortcut - 3, tr.value - 4
	if(taxgr_str) free(taxgr_str);
	if(res == 2)    {
	    n = PQntuples(result);
	    //printf("n = %d \n", n);
	    if ( n > 0 ) rec->Add_Taxes_Info(rec->GetPosElemRef(npos)->tax_group, PQgetvalue(result, 0, 5),  n);
	    else rec->Add_Taxes_Info(rec->GetPosElemRef(npos)->tax_group, "",  n);
	    //printf("name = PQgetvalue(result, 0, 0) = %s \n", PQgetvalue(result, 0, 5));
	    
	    //else rec->Add_Taxes_Info(rec->GetPosElemRef(npos)->tax_group, PQgetvalue(result, 0, 5),  n);
	    if(n > 0)      {
		bool ch_base;
		for(int i = 0; i < n; i ++)        {
		    if(!strcmp(PQgetvalue(result, i, 1), "t"))             ch_base = true;
		    else            ch_base = false;
		    TaxRate taxrate(atoi(PQgetvalue(result, i, 0)) /*rate_id*/, atof(PQgetvalue(result, i, 4)) /*rate*/, ch_base /*change_base*/,  PQgetvalue(result, i, 3)/*shortcut*/, PQgetvalue(result, i, 2) /*longtitle*/);
		    rec->GetTaxElemRef(npos)->Add_Tax_Rate(taxrate);          
		}
	    }
	    PQclear(result);
	}	else ret = 7;
    }  else
	rec->Add_Taxes_Info(rec->GetPosElemRef(npos)->tax_group, "", n);
    
    return ret;
}

//==================================================================================//
int Registration::Overflow_Control(double checksum, double newsum, double oldsum)
{
// puts("int Registration::Overflow_Control(double checksum, double newsum, double oldsum)");
// puts("======================================");
 // printf("sum = %f,\n newsumpos = %f,\n oldsumpos %f\n", checksum, newsum, oldsum);
// puts("======================================");

  if(newsum > 99999999.99) return 10;
  if(checksum - oldsum + newsum > 99999999.99) return 11;
  return 0;
}

//==================================================================================//
//code - штрих-код товара
//returns :
//0 - все нормально
//3 - не верный штрих-код товара
//7 - запрос в БД не был выполнен, смотреть логфайл
int Registration::Bar_Get_Product(const char *code)
{
//puts("Registration::Bar_Get_Product(const char *code)");
  int res = Query_by_Bar_Code(code);
//puts("==============================================================");
// printf("res = %d \n", res);
//puts("==============================================================");
  if(res == 2)  {
    int n = PQntuples(result);
    if(n > 0) return 0;
    else    {      PQclear(result);      return 3;    }
  }
  else return 7;
}

//==================================================================================//
//code - внутренний код товара
//returns : 
//0 - все нормально
//4 - не верный код товара
//7 - запрос в БД не был выполнен, смотреть логфайл
int Registration::Internal_Get_Product(const char *code)
{
//puts("Registration::Internal_Get_Product(const char *code)");
  int res = Query_by_Internal_Code(code);
  if(res == 2)
  {
    int n = PQntuples(result);
    if(n > 0) return 0;
    else
    {    
      PQclear(result);
      return 4;
    }
  }
  else return 7;
}

//==================================================================================//
//q - необходимое количество товара
//return_fl : true - производится возврат товара
//returns : 
//0 - все нормально
//1 - продажа данного товара запрещена в карточке товара
//2 - возврат данного товара запрещен в карточке товара
//5 - нет требуемого количества товара
//6 - не верное имя товара в БД
//8 - попытка продать штучный товар как весосой
//9 - истек срок годности
// 93 - продажа  товаров запрещена в настройках контроля регистраций
// 94 - возврат данного товара запрещен в настройках контроля регистраций
// 95 - истек срок годности
// 96 - продажа весового товара запрещена в настройках контроля регистраций
// 97 - редактирование цены запрещено в карточке товара
// 98 - запрещено редактирование количества
int Registration::Check_Product_Atr(double q, bool return_fl)
{
    //printf("Registration::Check_Product_Atr(%f)\n", q);
    //  int res = 0;
    int flags = atoi(PQgetvalue(result, 0, 8));
    
    // Проверка параметров при регистрации товара
   
    // Проверка флага 'разрешить продажи'
    //printf("sp->control_sale = %d \n", sp->control_sale); // 0- ware card 1- да 2- нет
    if ( !return_fl && sp->control_sale == NO ) return 93;
    if ( !return_fl && (sp->control_sale == WARECARD) && ( (flags & ALLOWREGISTRATION) == 0 ) ) return 1; 
    
    if ( return_fl && sp->control_back == NO ) return 94;
    if ( return_fl && sp->control_back == WARECARD && ((flags & ALLOWRETURN) == 0) ) return 2;   
    
    //if ( ( (flags & QUANTITYEDIT) == 0 ) && (q > 1) )    return 97;
    
    if ( ((flags & QUANTITYEDIT) == 0) && internal_tmp != 1 ) return 98;
    
    
    //printf("q = %f \n", q);
    // Проверка соответствия флагу 'разрешить дробное количество'
    if ( sp->control_double == NO && ((q - floor(q)) != 0)  ) return 102;
    if ( sp->control_double == WARECARD && (flags & ALLOWFRACTIONAL) == 0 && ((q - floor(q)) > 0.000001 )  ) return 8;
    
    if ( !return_fl ) {
	bool remains_control = false;
	// списание остатков
	if ( sp->control_remains == YES ) remains_control = true;
	if ( (sp->control_remains == WARECARD) && ((int) (flags & WRITEOFFREMAINS) != 0) ) remains_control =  true; 
	
	// отрицательные остатки
	if ( (sp->control_negative_remains == NO) && (remains_control) && (atof(PQgetvalue(result, 0, 3)) < q) ) return 5;    
	if ( (sp->control_negative_remains == WARECARD) && (remains_control) && ((int) (flags & ALLOWNEGATIVEQUANTTITY) == 0) && (atof(PQgetvalue(result, 0, 3)) < q) )   return 5;    
    }
    
    //Проверка срока годности
    if ( !return_fl ) {    
	if ( sp->control_exparation == 1 && strcmp(PQgetvalue(result, 0, 5), "f") == 0  ) {
	    return 95;
	}
    }
  
  return 0;
}

//==================================================================================//
//code - код товара (внутренний или штрих-)
//fl : true - использовать штрих-код товара, false - исрпользовать внутренний код товара
//npos : позиция чека, в которую будет добавлен товар
void Registration::Get_Check_Position(const char *code, bool fl, int &npos, Receipt *rec)
{
//puts("void Registration::Get_Check_Position(const char *code, bool fl, int &npos, Receipt *rec)");
  //Определиние позиции чека в зависимости от настройки объединения позиций
  if(sp->association_positions == ALLASSOCIATION) //Объединяем все позиции с одинаковыми товарами
    npos = rec->FindEquilPosition(code, !fl);		// ищет позиции с таким товаром
  else if(sp->association_positions == NOTFACTORIALASSOCIATION) //Объединяем тольно позиции с штучным товаром
  {
    //printf("<<<<<<<<<<<<<<<<\n<%s> %d\n>>>>>>>>>>>>>>>>\n", PQgetvalue(result, 0, 8), atoi(PQgetvalue(result, 0, 8)) & ALLOWFRACTIONAL);
    if((atoi(PQgetvalue(result, 0, 8)) & ALLOWFRACTIONAL) == 0)
    {  //  printf("<<<<<<<<<<<<<<<<\n<%s>\n>>>>>>>>>>>>>>>>\n", PQgetvalue(result, 0, 8));
      npos = rec->FindEquilPosition(code, !fl);		// ищет позиции с таким товаром только если он штучный
    }
    else
      npos = -1;
  }
  else if(sp->association_positions == NOTASSOCIATION) //Не объединяем позиции 
    npos = -1;
}

//==================================================================================//
#define QUERY_INT "SELECT wb.barcode, w.internal_id, w.price, w.quantity, w.min_price, now() <= w.best_before, w.shortcut, w.longtitle, w.flags, w.tax_group_id, w.auto_scheme_id, w.fix_scheme_id, wb.coefficient, -1::numeric, ''::character varying, 0::numeric FROM Ware w LEFT JOIN ware_barcode wb ON wb.internal_id = w.internal_id WHERE w.internal_id = '"
/*#define QUERY_INT "SELECT barcode, internal_id, price, quantity, min_price, now() <= best_before, shortcut, longtitle, flags, tax_group_id, auto_scheme_id, fix_scheme_id FROM Ware WHERE internal_id = "*/
int Registration::Query_by_Internal_Code(const char *code)
{
//puts("Registration::Query_by_Internal_Code(const char *code)");
  int state;
  char *str; 
    
  //Поиск данных на товар по внутреннему коду
  str = (char *) calloc(strlen(QUERY_INT) + strlen(code) + 3, sizeof(char));
if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
  strcpy(str, QUERY_INT);
  strcat(str, code);
  strcat(str, "'");
  //printf("str = %s \n", str);
  state = doSQL(myconnection, str);
  free(str);
  return state;
}

//==================================================================================//
#define QUERY_BAR "SELECT barcode, internal_id, price, quantity, min_price, now() <= best_before, shortcut, longtitle, flags, tax_group_id, auto_scheme_id, fix_scheme_id, coefficient, operator_id, account, fee FROM ware_by_barcode('"
//#define QUERY_BAR "SELECT wb.barcode, w.internal_id, w.price, w.quantity, w.min_price, now() <= w.best_before, w.shortcut, w.longtitle, w.flags, w.tax_group_id, w.auto_scheme_id, w.fix_scheme_id, wb.coefficient FROM Ware w, ware_barcode wb WHERE wb.internal_id = w.internal_id AND  wb.barcode = '"
/*#define QUERY_BAR "SELECT barcode, internal_id, price, quantity, min_price, now() <= best_before, shortcut, longtitle, flags, tax_group_id, auto_scheme_id, fix_scheme_id FROM Ware WHERE barcode = '"*/
int Registration::Query_by_Bar_Code(const char *code)
{
//puts("Registration::Query_by_Bar_Code(const char *code)");
  int state;
  char *str;

  //Поиск данных на товар по штрих коду
  str = (char *) calloc(strlen(QUERY_BAR) + strlen(code) + 3, sizeof(char));
 if(str == NULL) printf("NULL CALLOC!!! parameter str\n");

  strcpy(str, QUERY_BAR);
  strcat(str, code);
  strcat(str, "')");
  state = doSQL(myconnection, str);
  free(str);  
  return state;
}

//==================================================================================//
#define QUERY_PATTERN "SELECT pattern, multiplier FROM Weit_Pattern WHERE prefix = '"
int Registration::Query_Pattern(const char *prefix)
{
//puts("Registration::Query_Pattern(const char* prefix)");
   int state;
  char *str;

  str = (char *) calloc(strlen(QUERY_PATTERN) + strlen(prefix) + 2, sizeof(char));
 if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
  strcpy(str, QUERY_PATTERN);
  strcat(str, prefix);
  strcat(str, "'");
  state = doSQL(myconnection, str);
  free(str);  
  return state;
}

//==================================================================================//
#define QUERY_TAXES "SELECT trg.tax_rate_id, trg.base_flag, tr.longtitle, tr.shortcut, tr.value, tg.shortcut FROM Tax_Rate_Group trg, Tax_Rate tr, Tax_Group tg WHERE (trg.tax_rate_id = tr.tax_rate_id)  AND (trg.tax_group_id = tg.tax_group_id) AND (trg.tax_group_id = "
#define QUERY_TAXES_ORDER " ORDER BY trg.order_id"
int Registration::Query_Taxes(const char *taxgroup)
{
//puts("Registration::Query_Taxes(const char *taxgroup)");
  int state;
  char *str;

  str = (char *) calloc(strlen(QUERY_TAXES) + strlen(QUERY_TAXES_ORDER) + strlen(taxgroup) + 2, sizeof(char));
 if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
  strcpy(str, QUERY_TAXES);
  strcat(str, taxgroup);
  strcat(str, ")");
  strcat(str, QUERY_TAXES_ORDER);

  state = doSQL(myconnection, str);
//puts("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
  free(str);  
  return state;
}

////////////////////////////////////////////////////////////////////////VISUAL SEARCH////////////////////////////////////////////////////////////////////////////
//==================================================================================//
int Registration::Get_Num_Info(const char *group_id, bool fl)
//fl: true - group, false - Registration 
//return :
//0 - нет записей в этом каталоге
//-1 - нет связи с БД
{
//puts("Registration::Get_Num_Info(const char *group_id, bool fl)");
/*  if(fl)
  {
    if(Query_Group(group_id) != 2)
      return -1;
  }
  else if(Query_Goods(group_id) != 2) return -1;
 
  int n = PQntuples(result);
printf("ntuples - %d\n", n);
  if(n == 0) PQclear(result);
  return n;*/
  if (fl) return Query_Group_Cnt(group_id);
  return Query_Goods_Cnt(group_id);
}
//==================================================================================//
int Registration::Get_List_By_Parent(const char *group_id, bool fl)
//fl: true - group, false - Registration 
//return :
//0 - нет записей в этом каталоге
//-1 - нет связи с БД
{
//puts("Registration::Get_List_By_Parent(const char *group_id, bool fl)");
  if(fl)
  {
    if(Query_Group(group_id) != 2)
      return -1;
  }
  else if(Query_Goods(group_id) != 2) return -1;
 
  int n = PQntuples(result);
  if(n == 0) PQclear(result);
  return n;
}

//==================================================================================//
// group_id - идентификатор теаущей группы
// name - имя родительской группы, заполняется внутри функции
// pgroup - идентификатор родительской группы, заполняется внутри функции
int Registration::Get_Parent_Info(const char *group_id, char *name, char *pgroup)
{
//puts("Registration::Get_Parent_Info(const char *group_id, char *name, char *pgroup)");

  if(Query_Parent_Group(group_id) == 2)
  {
    if(PQntuples(result) == 0)
    {
      PQclear(result);
      return 1;
    }
    strcpy(name, PQgetvalue(result, 0, 0));
    strcpy(pgroup, PQgetvalue(result, 0, 1));
    PQclear(result);
    return 0;
  }
  else return -1;
}

//==================================================================================//
void Registration::Get_Group_Info(char *name, char *group_id, int i, int n)
{
//puts("Registration::Get_Group_Info(char *name, char *group_id, int i, int n)");
  strcpy(group_id, PQgetvalue(result, i, 0));
  strcpy(name, PQgetvalue(result, i, 1));
  if(n == i + 1) PQclear(result); 
}

//==================================================================================//
void Registration::Get_Prod_Info(char *longtitle, char *shortcut, char *price, char *quantity, char *bar_code, char *internal_code, int i, int n)
{
  strcpy(longtitle, PQgetvalue(result, i, 0));
  strcpy(shortcut, PQgetvalue(result, i, 1));
  strcpy(price, PQgetvalue(result, i, 2));
  strcpy(quantity, PQgetvalue(result, i, 3));
  strcpy(bar_code, PQgetvalue(result, i, 4));
  strcpy(internal_code, PQgetvalue(result, i, 5));
  if (n == i + 1) PQclear(result); 
//printf("end\n");
}

//==================================================================================//
int Registration::Get_Num_Search_Info(const char *pattern, int pattern_type)
// return :
// 0 - нет записей соответствующих указанному шаблону
// -1 - нет связи с БД
// n - кол-во записей в запросе	
{
//puts("Registration::Get_Num_Search_Info(const char *group_id, int pattern_type)");
  if(pattern_type == 1)
  {
    return Query_Cnt_by_IntCode(pattern);
  }
  if (pattern_type == 2)
  {
    return Query_Cnt_by_BarCode(pattern);
  }
  if (pattern_type == 3)
  {
    return Query_Cnt_by_ShCut(pattern);
  }
  return 0;
 }
//==================================================================================//
int Registration::Get_List_By_Pattern(const char *pattern, int pattern_type)
//return :
// 0 - нет записей соответствующих указанному шаблону
// -1 - нет связи с БД
// n - кол-во записей в запросе
{
//puts("Registration::Get_List_By_Pattern(const char *group_id, int pattern_type)");
  if(pattern_type == 1)
  {
    if(Query_by_Internal_Code_Pattern(pattern) != 2)
      return -1;
  }
  else if(pattern_type == 2)
  {
    if(Query_by_Bar_Code_Pattern(pattern) != 2)
      return -1;
  }
  else if(pattern_type == 3)
  {
    if(Query_by_Shortcut_Pattern(pattern) != 2)
      return -1;
  }
  int n = PQntuples(result);
  if(n == 0) PQclear(result);
  return n;
}
//==================================================================================//
#define QUERY_GROUP_CNT "SELECT count(group_id) FROM Ware_Group WHERE parent_group_id "
#define QUERY_GROUP_W_CNT "IS NULL"
int Registration::Query_Group_Cnt(const char *gr)
{
//puts("int Registration::Query_Group(const char *gr)");
  int state;
  char *str;

  str = (char *) calloc(strlen(QUERY_GROUP_CNT) + strlen(QUERY_GROUP_W_CNT ) + strlen(gr) + 1, sizeof(char));
 if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
  strcpy(str, QUERY_GROUP_CNT);
  if(!strcmp(gr, "0"))
    strcat(str, QUERY_GROUP_W_CNT);
  else
  {
    strcat(str, "= ");
    strcat(str, gr);
  }
  state = doSQL(myconnection, str);
  free(str);
  if (state !=2)
       return -1;     
  int n = PQntuples(result);
  if (n == 0) {PQclear(result);return 0;}
  n = atoi(PQgetvalue(result, 0, 0));    
  PQclear(result);
  return n;
}

//==================================================================================//
#define QUERY_GROUP "SELECT group_id, longtitle FROM Ware_Group WHERE parent_group_id "
#define QUERY_GROUP_ORDER " ORDER BY "
#define QUERY_GROUP_W "IS NULL"
int Registration::Query_Group(const char *gr)
{
//puts("int Registration::Query_Group(const char *gr)");
  int state;
  char *str;

  str = (char *) calloc(strlen(QUERY_GROUP) + strlen(QUERY_GROUP_ORDER) + strlen(QUERY_GROUP_W ) + strlen(gr) + 30, sizeof(char));
 if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
  strcpy(str, QUERY_GROUP);
  if(!strcmp(gr, "0"))
    strcat(str, QUERY_GROUP_W);
  else
  {
    strcat(str, "= ");
    strcat(str, gr);
  }
  
  switch(sp->order_search_result)
  {
    case 0 :
      strcat(str, QUERY_GROUP_ORDER);
      strcat(str, "group_id");
      break;
    case 2 :
      strcat(str, QUERY_GROUP_ORDER);	
      strcat(str, "longtitle");
      break;
  }
  state = doSQL(myconnection, str);
  free(str);  
  return state;
}
//==================================================================================//
#define QUERY_GOODS_CNT "SELECT count(internal_id) FROM Ware WHERE group_id "
#define QUERY_GOODS_W_CNT "IS NULL"
int Registration::Query_Goods_Cnt(const char *gr)
{
//puts("int Registration::Query_Goods_Cnt(const char *gr)");
  int state;
  char *str;

  str = (char *) calloc(strlen(QUERY_GOODS_CNT) + strlen(QUERY_GOODS_W_CNT ) + strlen(gr) + 1, sizeof(char));
 if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
  strcpy(str, QUERY_GOODS_CNT);
  if(!strcmp(gr, "0"))
    strcat(str, QUERY_GOODS_W_CNT);
  else
  {
    strcat(str, "= ");
    strcat(str, gr);
  }
  state = doSQL(myconnection, str);
  //printf("state = <%d>\n",state);
  free(str);
  if (state !=2)
       return -1;     
  int n = PQntuples(result);
  if (n == 0) {PQclear(result); return 0;}
  n = atoi(PQgetvalue(result, 0, 0));    
  PQclear(result);
  return n;
}
//==================================================================================//
#define QUERY_GOODS "SELECT w.longtitle, w.shortcut, w.price, w.quantity, wb.barcode, w.internal_id FROM Ware w LEFT JOIN ware_barcode wb ON wb.internal_id = w.internal_id WHERE (wb.main_barcode = 't' OR wb.main_barcode IS NULL) AND w.group_id "
/*#define QUERY_GOODS "SELECT longtitle, shortcut, price, quantity, barcode, internal_id FROM Ware WHERE group_id "*/
#define QUERY_GOODS_ORDER " ORDER BY  "
#define QUERY_GOODS_W "IS NULL"
int Registration::Query_Goods(const char *gr)
{
//puts("int Registration::Query_Goods(const char *gr)");
  int state;
  char *str;

  str = (char *) calloc(strlen(QUERY_GOODS) + strlen(QUERY_GOODS_ORDER) + strlen(QUERY_GOODS_W) + strlen(gr) + strlen(ORDERBYCODE) + 1, sizeof(char));
 if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
  strcpy(str, QUERY_GOODS);
  if(!strcmp(gr, "0"))
    strcat(str, QUERY_GOODS_W);
  else
  {
    strcat(str, "= ");
    strcat(str, gr);
  }
  strcat(str, QUERY_GOODS_ORDER);
  switch(sp->order_search_result)
  {
    case 0 :
      strcat(str, ORDERBYCODE);
      break;
    case 1 :
      strcat(str, ORDERBYBARCODE);
      break;
    case 2 :
      strcat(str, ORDERBYTITLE);
      break;
  }

  state = doSQL(myconnection, str); 
  free(str);  
  return state;
}

//==================================================================================//
#define QUERY_PARENT_GROUP "SELECT longtitle, parent_group_id FROM Ware_Group WHERE group_id = "
int Registration::Query_Parent_Group(const char *gr)
{
//puts("int Registration::Query_Parent_Group(const char *gr)");
  int state;
  char *str;

  str = (char *) calloc(strlen(QUERY_PARENT_GROUP) + strlen(gr) + 1, sizeof(char));
 if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
  strcpy(str, QUERY_PARENT_GROUP);
  strcat(str, gr);
  state = doSQL(myconnection, str); 
  free(str);  
  return state;
}
//==================================================================================//
#define QUERY_GOODS_INT_CNT "SELECT COUNT(w.internal_id) FROM Ware w LEFT JOIN ware_barcode wb ON wb.internal_id = w.internal_id WHERE w.internal_id ~~* '"

int Registration::Query_Cnt_by_IntCode(const char *pattern)
{
//puts("int Registration::Query_Cnt_by_IntCode(const char *pattern)");
  int state;
  char *str;
  
  str = (char *) calloc(strlen(QUERY_GOODS_INT_CNT) + strlen(pattern) + 3 + 1, sizeof(char));
 if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
  strcpy(str, QUERY_GOODS_INT_CNT);
  strcat(str, pattern);
  strcat(str, "%' ");
  state = doSQL(myconnection, str);
  free(str);
  if (state !=2)
       return -1;     
  int n = PQntuples(result);
  if (n == 0) {PQclear(result);return 0;}
  n = atoi(PQgetvalue(result, 0, 0)); 
  PQclear(result);
  return n;
}

//==================================================================================//
#define QUERY_GOODS_INT "SELECT w.longtitle, w.shortcut, w.price, quantity, wb.barcode, w.internal_id FROM Ware w LEFT JOIN ware_barcode wb ON wb.internal_id = w.internal_id WHERE w.internal_id ~~* '"
int Registration::Query_by_Internal_Code_Pattern(const char *pattern)
{
//puts("int Registration::Query_by_Internal_Code_Pattern(const char *pattern)");
  int state;
  char *str;
  
  str = (char *) calloc(strlen(QUERY_GOODS_INT) + strlen(QUERY_GOODS_ORDER) + strlen(pattern) + strlen(ORDERBYCODE) + 3 + 1, sizeof(char));
 if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
  strcpy(str, QUERY_GOODS_INT);
  strcat(str, pattern);
  strcat(str, "%' ");
  strcat(str, QUERY_GOODS_ORDER);
  switch(sp->order_search_result)
  {
    case 0 :
      strcat(str, ORDERBYCODE);
      break;
    case 1 :
      strcat(str, ORDERBYBARCODE);
      break;
    case 2 :
      strcat(str, ORDERBYTITLE);
      break;
  }
  printf("vs by code str = %s \n", str);
  state = doSQL(myconnection, str); 
  free(str);  
  return state;
}
//==================================================================================//
#define QUERY_GOODS_BAR_CNT "SELECT COUNT(w.internal_id) FROM Ware w, ware_barcode wb WHERE wb.internal_id = w.internal_id AND wb.barcode ~~* '"
int Registration::Query_Cnt_by_BarCode(const char *pattern)
{
//puts("int Registration::Query_Cnt_by_BarCode(const char *pattern)");
  int state;
  char *str;

  str = (char *) calloc(strlen(QUERY_GOODS_BAR_CNT) + strlen(pattern) + 3 + 1, sizeof(char));
 if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
  strcpy(str, QUERY_GOODS_BAR_CNT);
  strcat(str, pattern);
  strcat(str, "%' ");
  
  state = doSQL(myconnection, str);
  free(str);
  if (state !=2)
       return -1;     
  int n = PQntuples(result);
  if (n == 0) {PQclear(result);return 0;}
  n = atoi(PQgetvalue(result, 0, 0)); 
  PQclear(result);
  return n;
}
//==================================================================================//
#define QUERY_GOODS_BAR "SELECT w.longtitle, w.shortcut, w.price, w.quantity, wb.barcode, w.internal_id FROM Ware w, ware_barcode wb WHERE wb.internal_id = w.internal_id AND wb.barcode ~~* '"
int Registration::Query_by_Bar_Code_Pattern(const char *pattern)
{
//puts("int Registration::Query_by_Bar_Code_Pattern(const char *pattern)");
  int state;
  char *str;

  str = (char *) calloc(strlen(QUERY_GOODS_BAR) + strlen(QUERY_GOODS_ORDER) + strlen(pattern) + strlen(ORDERBYCODE) + 3 + 1, sizeof(char));
 if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
  strcpy(str, QUERY_GOODS_BAR);
  strcat(str, pattern);
  strcat(str, "%' ");
  strcat(str, QUERY_GOODS_ORDER);
  switch(sp->order_search_result)
  {
    case 0 :
      strcat(str, ORDERBYCODE);
      break;
    case 1 :
      strcat(str, ORDERBYBARCODE);
      break;
    case 2 :
      strcat(str, ORDERBYTITLE);
      break;
  }
  //printf("vs by barcode = %s \n ", str);
  state = doSQL(myconnection, str); 
  free(str);  
  return state;
}
//==================================================================================//
#define QUERY_GOODS_SHCUT_CNT "SELECT COUNT(w.internal_id) FROM Ware w LEFT JOIN ware_barcode wb ON wb.internal_id = w.internal_id WHERE upper(w.longtitle) ~~*  upper('%"
int Registration::Query_Cnt_by_ShCut(const char *pattern)
{
//puts("int Registration::Query_Cnt_by_ShCut(const char *pattern)");
  int state;
  char *str;

  str = (char *) calloc(strlen(QUERY_GOODS_SHCUT_CNT) + strlen(pattern) + 3 + 1, sizeof(char));
 if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
  strcpy(str, QUERY_GOODS_SHCUT_CNT);
  strcat(str, pattern);
  strcat(str, "%')");
   state = doSQL(myconnection, str);
  free(str);
  if (state !=2)
       return -1;     
  int n = PQntuples(result);
  if (n == 0) {PQclear(result);return 0;}
  n = atoi(PQgetvalue(result, 0, 0)); 
  PQclear(result);
  return n;
}
//==================================================================================//
#define QUERY_GOODS_SHORTCUT "SELECT w.longtitle, w.shortcut, w.price, w.quantity, wb.barcode, w.internal_id FROM Ware w LEFT JOIN ware_barcode wb ON wb.internal_id = w.internal_id WHERE upper(w.longtitle) ~~*  upper('%"
int Registration::Query_by_Shortcut_Pattern(const char *pattern)
{
//puts("int Registration::Query_by_Shortcut_Pattern(const char *pattern)");
  int state;
  char *str;

  str = (char *) calloc(strlen(QUERY_GOODS_SHORTCUT) + strlen(QUERY_GOODS_ORDER) + strlen(pattern) + strlen(ORDERBYCODE) + 3 + 1, sizeof(char));
 if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
  strcpy(str, QUERY_GOODS_SHORTCUT);
  strcat(str, pattern);
  strcat(str, "%')");
  strcat(str, QUERY_GOODS_ORDER);
  switch(sp->order_search_result)
  {
    case 0 :
      strcat(str, ORDERBYCODE);
      break;
    case 1 :
      strcat(str, ORDERBYBARCODE);
      break;
    case 2 :
      strcat(str, ORDERBYTITLE);
      break;
  }
  printf("vs by longtittle str = %s \n", str);
  state = doSQL(myconnection, str); 
  free(str);  
  return state;
}


//==================================================================================//
int Registration::Get_List(const char *area)
{
//puts("Registration::Get_List(const char *area)");
  if(Query_List_by_Area(area) != 2) return -1;
  
  int n = PQntuples(result);
  if(n == 0) PQclear(result);  
  return n;
}

//==================================================================================//
void Registration::Get_List_Position(char *&code, char *&value, char *&name, char *&shortcut, int *type, char * & incode, char* & cardcode, int i, int n)
{
//puts("Registration::Get_List_Position(char *&code = %s, char *&value = %s, char *&name = %s, char *&shortcut = %s, int *type = %d, int i = %d, int n = d)", code, value, name, shortcut, type, i, n);

  if(i < n)  {
    code = (char *) calloc(PQgetlength(result, i , 0) + 1, sizeof(char));
    value = (char *) calloc(PQgetlength(result, i , 1) + 2, sizeof(char));
    name = (char *) calloc(PQgetlength(result, i , 3) + 1, sizeof(char));
    shortcut = (char *) calloc(PQgetlength(result, i , 4) + 1, sizeof(char));
    incode = (char* ) calloc(PQgetlength(result, i , 5) + 1, sizeof(char));
    cardcode = (char* ) calloc(PQgetlength(result, i , 6) + 1, sizeof(char));
    strcpy(code, PQgetvalue(result, i, 0));
    strcpy(value, PQgetvalue(result, i, 1));
    strcpy(name, PQgetvalue(result, i, 3));
    strcpy(shortcut, PQgetvalue(result, i, 4));
    strcpy(incode, PQgetvalue(result, i, 5));
    strcpy(cardcode, PQgetvalue(result, i, 6));
    *type = atoi(PQgetvalue(result, i, 2));
  }
  if(n == i + 1) PQclear(result);
}

#define QUERY_LIST_AREA "SELECT external_id, value, type, longtitle, shortcut, external_id, cardcode FROM Fix_Reduction, activescheme WHERE area = '"
#define QUERY_LIST_AREA_ORDER "' AND scheme_id = activescheme_id AND show = 't'  ORDER BY external_id"
//==================================================================================//
int Registration::Query_List_by_Area(const char *area)
{
//puts("Registration::Query_List_by_Area(const char *area)");
  char * str;
  int state;   

  str = (char *) calloc(strlen(QUERY_LIST_AREA) + strlen(QUERY_LIST_AREA_ORDER) + strlen(area) + 1, sizeof(char));
 if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
  strcpy(str, QUERY_LIST_AREA);
  strcat(str, area);
  strcat(str, QUERY_LIST_AREA_ORDER);

  state = doSQL(myconnection, str);
 
  free(str);
  return state; 
}

//////////////////////////////////////////////////////////////////////////////UPDATE/////////////////////////////////////////////////////////////////////////////////

//==================================================================================//
// 1 - списание остатков отключено в настройках 
// 2 - списание остатков запрещено в карточке товара
// 
int Registration::Update_Goods_Quantity(Receipt *rec)
{

    char *q_str = NULL;
    for(int i = 0; i < rec->record_num; i ++)  {
	if ( rec->GetPosElemRef(i)->enable_flag ) {	    
	    q_str = ftoa(rec->GetPosElemRef(i)->GetQuantity(), 3);
	    
	    char* ssdfsdrfg = (char*) calloc(strlen(q_str) + 8, sizeof(char));
	    if ( rec->GetCheckType() == CHECK_RETURN ) strcat(ssdfsdrfg, "-");
	    strcat(ssdfsdrfg, q_str);
	    free(q_str);
	    
	    Update_Quantity(ssdfsdrfg, rec->GetPosElemRef(i)->GetCode());    
	    free(ssdfsdrfg);
	}
    }	
}


#define SELECT_FLAGS "SELECT flags FROM ware WHERE internal_id = '"
//==================================================================================//
int Registration::GetFlags(const char* ware_code, int &flags )
{
  char * str;
  int state;   

  str = (char *) calloc(strlen(SELECT_FLAGS) + strlen(ware_code) + 2, sizeof(char));
  if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
  strcpy(str, SELECT_FLAGS);
  strcat(str, ware_code);
  strcat(str, "'");
  state = doSQL(myconnection, str);
  
  free(str);
  
  if (state == 2) flags = atoi(PQgetvalue(result, 0, 0));
  PQclear(result);
  
  return state; 
}


#define UPDATE_QUANTITY "UPDATE Ware SET quantity = quantity - "
#define UPDATE_QUANTITY_WHERE " WHERE internal_id = '"
//==================================================================================//
int Registration::Update_Quantity(const char *quant, const char *code)
{
    //puts("Registration::Update_Quantity(const char *quant, const char *code)");
    
    //puts("Registration::Update_Goods_Quantity(Receipt *rec)");
    
    if ( sp->control_remains == NO )  return 1;	
    
    if ( sp->control_remains == WARECARD ) {
	int flags = -1;
	int state = GetFlags(code, flags);	
	//printf("flags = %d \n", flags);
	if ( flags == -1 ) return state;
	if ( (int) (flags & WRITEOFFREMAINS) == 0 ) return 2;
    }
    
    
    char * str;
    int state;   

    str = (char *) calloc(strlen(UPDATE_QUANTITY) + strlen(UPDATE_QUANTITY_WHERE) + strlen(quant) + strlen(code) + 3, sizeof(char));
    if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
    strcpy(str, UPDATE_QUANTITY);
    strcat(str, quant);
    strcat(str, UPDATE_QUANTITY_WHERE);
    strcat(str, code);
    strcat(str, "'");
    state = doSQL(myconnection, str);
    
    free(str);
    return state; 
}
//==================================================================================//
// 1 - discount = 0
// -1 - request error
#define GET_DISCOUNT_BARCODE_INFO "SELECT external_id, longtitle, shortcut, value, type, area, cardcode FROM fix_reduction WHERE barcode = '"
int Registration::GetDiscountBarcodeInfo(const char* barcode, char*& code, char*& name, char*& shortcut, double &value, int &type, bool &area, char*& card_code)
{
  
  if ( strlen(barcode) == 0 ) return 1;
  char * str;
  int state;   

  str = (char *) calloc(strlen(GET_DISCOUNT_BARCODE_INFO) + strlen(barcode) + 4, sizeof(char));
  if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
  strcpy(str, GET_DISCOUNT_BARCODE_INFO);
  strcat(str, barcode);
  strcat(str, "'");

  state = doSQL(myconnection, str);
  
  if ( state != 2 ) return -1;
  int n = PQntuples(result);
  if ( n != 1 ) {	
	PQclear(result);
	return 1;
  }

//  printf("n = %d \n", n);

  code = (char*) calloc(PQgetlength(result, 0, 0) + 2, sizeof(char));
  strcpy(code, PQgetvalue(result, 0, 0)); 


  name = (char*) calloc(PQgetlength(result, 0, 1) + 2, sizeof(char));
  //printf("PQgetvalue(result, 0, 1) = %s \n", PQgetvalue(result, 0, 1));
  strcpy(name, PQgetvalue(result, 0, 1)); 
  //printf("-----------name = %s ----------- \n", name);

  shortcut = (char*) calloc(PQgetlength(result, 0, 2) + 2, sizeof(char));
  //printf("PQgetlength(result, 0, 2) = %s \n", PQgetvalue(result, 0, 2));
  strcpy(shortcut, PQgetvalue(result, 0, 2)); 
  //printf("----------- shortcut = %s ----------- \n", shortcut);
  
  value = atoi(PQgetvalue(result, 0, 3));
  type = atoi(PQgetvalue(result, 0, 4));
  area = ( strcmp(PQgetvalue(result, 0, 5), "t") == 0 );
  
  card_code = (char*) calloc(PQgetlength(result, 0, 6) + 2, sizeof(char));
  //printf("PQgetvalue(result, 0, 6) = %s \n", PQgetvalue(result, 0, 6));
  strcpy(card_code, PQgetvalue(result, 0, 6)); 
  //printf("----------- card_code = %s ----------- \n", card_code);

  PQclear(result);
  
  free(str);
  return 0; 
	
}
//==================================================================================//
#define GET_DISCOUNT_CARDCODE_INFO "SELECT external_id, longtitle, shortcut, value, type, area, barcode FROM fix_reduction WHERE cardcode = '"
int Registration::GetDiscountCardcodeInfo(const char* card_code, char*& code, char*& name, char*& shortcut, double &value, int &type, bool &area, char*& barcode)
{
  
  if ( strlen(card_code) == 0 ) return 1;
  char * str;
  int state;   

  str = (char *) calloc(strlen(GET_DISCOUNT_CARDCODE_INFO) + strlen(card_code) + 4, sizeof(char));
  if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
  strcpy(str, GET_DISCOUNT_CARDCODE_INFO);
  strcat(str, card_code);
  strcat(str, "'");

  state = doSQL(myconnection, str);
  free(str);

  if ( state != 2 ) return -1;
  int n = PQntuples(result);
  if ( n != 1 ) {	
	PQclear(result);
	return 1;
  }

//  printf("n = %d \n", n);

  code = (char*) calloc(PQgetlength(result, 0, 0) + 2, sizeof(char));
  strcpy(code, PQgetvalue(result, 0, 0)); 

  name = (char*) calloc(PQgetlength(result, 0, 1) + 2, sizeof(char));
  //printf("PQgetvalue(result, 0, 1) = %s \n", PQgetvalue(result, 0, 1));
  strcpy(name, PQgetvalue(result, 0, 1)); 
  //printf("-----------name = %s ----------- \n", name);

  shortcut = (char*) calloc(PQgetlength(result, 0, 2) + 2, sizeof(char));
  //printf("PQgetlength(result, 0, 2) = %s \n", PQgetvalue(result, 0, 2));
  strcpy(shortcut, PQgetvalue(result, 0, 2)); 
  //printf("----------- shortcut = %s ----------- \n", shortcut);
  
  value = atoi(PQgetvalue(result, 0, 3));
  type = atoi(PQgetvalue(result, 0, 4));
  area = ( strcmp(PQgetvalue(result, 0, 5), "t") == 0 );
  
  barcode = (char*) calloc(PQgetlength(result, 0, 6) + 2, sizeof(char));
  //printf("PQgetvalue(result, 0, 6) = %s \n", PQgetvalue(result, 0, 6));
  strcpy(barcode, PQgetvalue(result, 0, 6)); 
  //printf("----------- card_code = %s ----------- \n", card_code);

  PQclear(result);
  
  
  return 0; 	
}

#define GET_QUANTEDIT_INFO "SELECT flags FROM ware WHERE internal_id = '"
#define GET_QUANTITY_INFO "SELECT quantity FROM ware WHERE internal_id = '"
//==================================================================================//
//return 0 - можно продавать;
// 1 - нельзя продавать;
// -1 - error;
int Registration::GetQuantityEditInfo(const char* ware_code, double q)
{
    int state = 0;
    
    char* str = (char*) calloc( strlen(GET_QUANTEDIT_INFO) + strlen(ware_code) + 2, sizeof(char) );
    
    strcat(str, GET_QUANTEDIT_INFO);
    strcat(str, ware_code);
    strcat(str, "'");
    
    state = doSQL(myconnection, str);
    free(str);
    
    if (state != 2) return -1;
    if ( PQntuples(result) != 1 ) {
	PQclear(result);
	return -1;    
    }
    
    int flags = atoi(PQgetvalue(result, 0, 0));
    
    PQclear(result);
    
    bool remains_control = false;
    // списание остатков
    if ( sp->control_remains == YES ) remains_control = true;    
    if ( (sp->control_remains == WARECARD) && ((int) (flags & WRITEOFFREMAINS) != 0) ) remains_control =  true; 
    
    bool control_negative_remains = true;
    // отрицательные остатки
    if ( sp->control_negative_remains == NO ) control_negative_remains = false;
    if ( (sp->control_negative_remains == WARECARD) && ( (int) (flags & ALLOWNEGATIVEQUANTTITY) != 0) ) control_negative_remains = false;
        
    
    state = 0;
    
    str = (char*) calloc( strlen(GET_QUANTITY_INFO) + strlen(ware_code) + 2, sizeof(char) );
    
    strcat(str, GET_QUANTITY_INFO);
    strcat(str, ware_code);
    strcat(str, "'");
    
    state = doSQL(myconnection, str);
    free(str);
    
    if (state != 2) return -1;
    if ( PQntuples(result) != 1 )    {	
	PQclear(result);
	return -1;    
    }
    
    double quantity = atof(PQgetvalue(result, 0, 0));
    
    PQclear(result);
    
    //printf("quantity = %f \n", quantity);
    //printf("q = %f \n", q);
    
    if ( (remains_control) && (!control_negative_remains) && (quantity - q < 0)  ) return 1;
    
    return 0;
    
}

#define GET_QUNTEDITFLAGS "SELECT flags FROM ware WHERE internal_id = '"
//==================================================================================//
int Registration::GetQuantityEditFlag(const char* ware_code)
{
    int state = 0;
    
    char* str = (char*) calloc( strlen(GET_QUNTEDITFLAGS) + strlen(ware_code) + 2, sizeof(char) );
    
    strcat(str, GET_QUNTEDITFLAGS);
    strcat(str, ware_code);
    strcat(str, "'");
    
    state = doSQL(myconnection, str);
    free(str);
    
    if (state != 2) return -1;
    if ( PQntuples(result) != 1 ) {
	PQclear(result);
	return -1;    
    }
    
    int flags = atoi(PQgetvalue(result, 0, 0));
    
    PQclear(result);
    
    if ( (int) (flags & QUANTITYEDIT) == 0 ) return 1;
    return 0;
    
}
//==================================================================================//

#define GET_QUNTEDITFLAGS_BY_CODE "SELECT flags FROM ware WHERE internal_id = '"
#define GET_QUNTEDITFLAGS_BY_BARCODE "SELECT flags FROM ware WHERE internal_id IN (SELECT internal_id FROM ware_barcode WHERE barcode = '"
//==================================================================================//
int Registration::GetQuantityEditFlag(const char* ware_code, bool type_code)
{
    int state = 0;
    
    char* str;
    
    if ( type_code ) {
	// barcode
	str = (char*) calloc( strlen(GET_QUNTEDITFLAGS_BY_BARCODE) + strlen(ware_code) + 3, sizeof(char) );
	strcat(str, GET_QUNTEDITFLAGS_BY_BARCODE);
	strcat(str, ware_code);
	strcat(str, "')");	
    } else {
	// code
	str = (char*) calloc( strlen(GET_QUNTEDITFLAGS_BY_CODE) + strlen(ware_code) + 2, sizeof(char) );
	strcat(str, GET_QUNTEDITFLAGS_BY_CODE);
	strcat(str, ware_code);
	strcat(str, "'");
    }
    
    state = doSQL(myconnection, str);
    free(str);

    if (state != 2) return -1;
    
    if ( PQntuples(result) != 1 ) {
	PQclear(result);
	return -1;    
    }
    
    int flags = atoi(PQgetvalue(result, 0, 0));
    
    PQclear(result);
    
    if ( (int) (flags & QUANTITYEDIT) == 0 ) return 1;	// запрещен
    return 0;
    
}

//==================================================================================//
int Registration::Get_Num_Info_Available(const char *group_id, bool fl)
{
    if (fl) return Query_Group_Cnt(group_id);
    return Query_Goods_Cnt_Available(group_id);
}
//==================================================================================//
#define QUERY_GOODS_CNT_A "SELECT count(internal_id) FROM Ware WHERE quantity > 0 AND group_id "
#define QUERY_GOODS_W_CNT_A "IS NULL"
int Registration::Query_Goods_Cnt_Available(const char *gr)
{
//puts("int Registration::Query_Goods_Cnt(const char *gr)");
  int state;
  char *str;

  str = (char *) calloc(strlen(QUERY_GOODS_CNT_A) + strlen(QUERY_GOODS_W_CNT_A ) + strlen(gr) + 1, sizeof(char));
 if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
  strcpy(str, QUERY_GOODS_CNT_A);
  if(!strcmp(gr, "0"))
    strcat(str, QUERY_GOODS_W_CNT_A);
  else
  {
    strcat(str, "= ");
    strcat(str, gr);
  }
  state = doSQL(myconnection, str);
  //printf("state = <%d>\n",state);
  free(str);
  if (state !=2)
       return -1;     
  int n = PQntuples(result);
  if (n == 0) {PQclear(result); return 0;}
  n = atoi(PQgetvalue(result, 0, 0));    
  PQclear(result);
  return n;

}
//==================================================================================//
int Registration::Get_Num_Search_Info_Available(const char *pattern, int pattern_type)
{
    if ( pattern_type == 1 )  {
	return Query_Cnt_by_IntCode_Available(pattern);
    }
    if (pattern_type == 2)  {
	return Query_Cnt_by_BarCode_Available(pattern);
    }
    if (pattern_type == 3)  {
	return Query_Cnt_by_ShCut_Available(pattern);
    }
    return 0;
}
//==================================================================================//
#define QUERY_GOODS_INT_CNT_A "SELECT COUNT(w.internal_id) FROM Ware w LEFT JOIN ware_barcode wb ON wb.internal_id = w.internal_id WHERE quantity > 0 AND w.internal_id ~~* '"
int Registration::Query_Cnt_by_IntCode_Available(const char *pattern)
{
    //puts("int Registration::Query_Cnt_by_IntCode(const char *pattern)");
  int state;
  char *str;
  
  str = (char *) calloc(strlen(QUERY_GOODS_INT_CNT_A) + strlen(pattern) + 3 + 1, sizeof(char));
 if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
  strcpy(str, QUERY_GOODS_INT_CNT_A);
  strcat(str, pattern);
  strcat(str, "%' ");
/*  strcat(str, QUERY_GOODS_ORDER);
  switch(sp->order_search_result)
  {
    case 0 :
      strcat(str, ORDERBYCODE);
      break;
    case 1 :
      strcat(str, ORDERBYBARCODE);
      break;
    case 2 :
      strcat(str, ORDERBYTITLE);
      break;
  }*/
  state = doSQL(myconnection, str);
  free(str);
  if (state !=2)
       return -1;     
  int n = PQntuples(result);
  if (n == 0) {PQclear(result);return 0;}
  n = atoi(PQgetvalue(result, 0, 0)); 
  PQclear(result);
  return n;
}
//==================================================================================//
#define QUERY_GOODS_BAR_CNT_A "SELECT COUNT(w.internal_id) FROM Ware w, ware_barcode wb WHERE quantity > 0 AND wb.internal_id = w.internal_id AND wb.barcode ~~* '"
/*#define QUERY_GOODS_BAR "SELECT longtitle, shortcut, price, quantity, barcode, internal_id FROM Ware WHERE barcode ~~* '"*/
int Registration::Query_Cnt_by_BarCode_Available(const char *pattern)
{
    //puts("int Registration::Query_Cnt_by_BarCode(const char *pattern)");
  int state;
  char *str;

  str = (char *) calloc(strlen(QUERY_GOODS_BAR_CNT_A) + strlen(pattern) + 3 + 1, sizeof(char));
 if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
  strcpy(str, QUERY_GOODS_BAR_CNT_A);
  strcat(str, pattern);
  strcat(str, "%' ");
/*  strcat(str, QUERY_GOODS_ORDER);
  switch(sp->order_search_result)
  {
    case 0 :
      strcat(str, ORDERBYCODE);
      break;
    case 1 :
      strcat(str, ORDERBYBARCODE);
      break;
    case 2 :
      strcat(str, ORDERBYTITLE);
      break;
  }*/
  
  state = doSQL(myconnection, str);
  free(str);
  if (state !=2)
       return -1;     
  int n = PQntuples(result);
  if (n == 0) {PQclear(result);return 0;}
  n = atoi(PQgetvalue(result, 0, 0)); 
  PQclear(result);
  return n;
}
//==================================================================================//
#define QUERY_GOODS_SHCUT_CNT_A "SELECT COUNT(w.internal_id) FROM Ware w LEFT JOIN ware_barcode wb ON wb.internal_id = w.internal_id WHERE quantity > 0 AND upper(w.longtitle) ~~*  upper('%"
int Registration::Query_Cnt_by_ShCut_Available(const char *pattern)
{
    //puts("int Registration::Query_Cnt_by_ShCut(const char *pattern)");
  int state;
  char *str;

  str = (char *) calloc(strlen(QUERY_GOODS_SHCUT_CNT_A) + strlen(pattern) + 3 + 1, sizeof(char));
 if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
  strcpy(str, QUERY_GOODS_SHCUT_CNT_A);
  strcat(str, pattern);
  strcat(str, "%')");
/*  strcat(str, QUERY_GOODS_ORDER);
  switch(sp->order_search_result)
  {
    case 0 :
      strcat(str, ORDERBYCODE);
      break;
    case 1 :
      strcat(str, ORDERBYBARCODE);
      break;
    case 2 :
      strcat(str, ORDERBYTITLE);
      break;
  }*/
   state = doSQL(myconnection, str);
  free(str);
  if (state !=2)
       return -1;     
  int n = PQntuples(result);
  if (n == 0) {PQclear(result);return 0;}
  n = atoi(PQgetvalue(result, 0, 0)); 
  PQclear(result);
  return n;
}

//==================================================================================//
int Registration::Get_List_By_Pattern_Available(const char *pattern, int pattern_type)
//return :
// 0 - нет записей соответствующих указанному шаблону
// -1 - нет связи с БД
// n - кол-во записей в запросе
{
//puts("Registration::Get_List_By_Pattern(const char *group_id, int pattern_type)");
  if(pattern_type == 1)
  {
    if(Query_by_Internal_Code_Pattern_Available(pattern) != 2)
      return -1;
  }
  else if(pattern_type == 2)
  {
    if(Query_by_Bar_Code_Pattern_Available(pattern) != 2)
      return -1;
  }
  else if(pattern_type == 3)
  {
    if(Query_by_Shortcut_Pattern_Available(pattern) != 2)
      return -1;
  }
  int n = PQntuples(result);
  if(n == 0) PQclear(result);
  return n;
}
//==================================================================================//
#define QUERY_GOODS_INT_A "SELECT w.longtitle, w.shortcut, w.price, quantity, wb.barcode, w.internal_id FROM Ware w LEFT JOIN ware_barcode wb ON wb.internal_id = w.internal_id WHERE w.quantity > 0 AND w.internal_id ~~* '"
/*#define QUERY_GOODS_INT "SELECT longtitle, shortcut, price, quantity, barcode, internal_id FROM Ware WHERE CAST(internal_id AS VARCHAR(20)) ~~* '" */
int Registration::Query_by_Internal_Code_Pattern_Available(const char *pattern)
{
//puts("int Registration::Query_by_Internal_Code_Pattern(const char *pattern)");
  int state;
  char *str;
  
  str = (char *) calloc(strlen(QUERY_GOODS_INT_A) + strlen(QUERY_GOODS_ORDER) + strlen(pattern) + strlen(ORDERBYCODE) + 3 + 1, sizeof(char));
 if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
  strcpy(str, QUERY_GOODS_INT_A);
  strcat(str, pattern);
  strcat(str, "%' ");
  strcat(str, QUERY_GOODS_ORDER);
  switch(sp->order_search_result)
  {
    case 0 :
      strcat(str, ORDERBYCODE);
      break;
    case 1 :
      strcat(str, ORDERBYBARCODE);
      break;
    case 2 :
      strcat(str, ORDERBYTITLE);
      break;
  }
  puts(str);
  state = doSQL(myconnection, str); 
  free(str);  
  return state;
}

//==================================================================================//

#define QUERY_GOODS_BAR_A "SELECT w.longtitle, w.shortcut, w.price, w.quantity, wb.barcode, w.internal_id FROM Ware w, ware_barcode wb WHERE w.quantity > 0 AND wb.internal_id = w.internal_id AND wb.barcode ~~* '"
int Registration::Query_by_Bar_Code_Pattern_Available(const char *pattern)
{
//puts("int Registration::Query_by_Bar_Code_Pattern(const char *pattern)");
  int state;
  char *str;

  str = (char *) calloc(strlen(QUERY_GOODS_BAR_A) + strlen(QUERY_GOODS_ORDER) + strlen(pattern) + strlen(ORDERBYCODE) + 3 + 1, sizeof(char));
 if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
  strcpy(str, QUERY_GOODS_BAR_A);
  strcat(str, pattern);
  strcat(str, "%' ");
  strcat(str, QUERY_GOODS_ORDER);
  switch(sp->order_search_result)
  {
    case 0 :
      strcat(str, ORDERBYCODE);
      break;
    case 1 :
      strcat(str, ORDERBYBARCODE);
      break;
    case 2 :
      strcat(str, ORDERBYTITLE);
      break;
  }
  state = doSQL(myconnection, str); 
  free(str);  
  return state;
}
//==================================================================================//

#define QUERY_GOODS_SHORTCUT_A "SELECT w.longtitle, w.shortcut, w.price, w.quantity, wb.barcode, w.internal_id FROM Ware w LEFT JOIN ware_barcode wb ON wb.internal_id = w.internal_id WHERE w.quantity > 0 AND upper(w.longtitle) ~~*  upper('%"
int Registration::Query_by_Shortcut_Pattern_Available(const char *pattern)
{
//puts("int Registration::Query_by_Shortcut_Pattern(const char *pattern)");
  int state;
  char *str;

  str = (char *) calloc(strlen(QUERY_GOODS_SHORTCUT_A) + strlen(QUERY_GOODS_ORDER) + strlen(pattern) + strlen(ORDERBYCODE) + 3 + 1, sizeof(char));
 if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
  strcpy(str, QUERY_GOODS_SHORTCUT_A);
  strcat(str, pattern);
  strcat(str, "%')");
  strcat(str, QUERY_GOODS_ORDER);
  switch(sp->order_search_result)
  {
    case 0 :
      strcat(str, ORDERBYCODE);
      break;
    case 1 :
      strcat(str, ORDERBYBARCODE);
      break;
    case 2 :
      strcat(str, ORDERBYTITLE);
      break;
  }
  state = doSQL(myconnection, str); 
  free(str);  
  return state;
}


//==================================================================================//

int Registration::Get_List_By_Parent_Available(const char *group_id, bool fl)
//fl: true - group, false - Registration 
//return :
//0 - нет записей в этом каталоге
//-1 - нет связи с БД
{
//puts("Registration::Get_List_By_Parent(const char *group_id, bool fl)");
  if(fl)
  {
    if(Query_Group(group_id) != 2)
      return -1;
  }
  else if(Query_Goods_Available(group_id) != 2) return -1;
 
  int n = PQntuples(result);
  if(n == 0) PQclear(result);
  return n;
}
//==================================================================================//
#define QUERY_GOODS_A "SELECT w.longtitle, w.shortcut, w.price, w.quantity, wb.barcode, w.internal_id FROM Ware w LEFT JOIN ware_barcode wb ON wb.internal_id = w.internal_id WHERE w.quantity > 0 AND (wb.main_barcode = 't' OR wb.main_barcode IS NULL) AND w.group_id "
#define QUERY_GOODS_W_A "IS NULL"
int Registration::Query_Goods_Available(const char *gr)
{
//puts("int Registration::Query_Goods(const char *gr)");
  int state;
  char *str;

  str = (char *) calloc(strlen(QUERY_GOODS_A) + strlen(QUERY_GOODS_ORDER) + strlen(QUERY_GOODS_W_A) + strlen(gr) + strlen(ORDERBYCODE) + 1, sizeof(char));
 if(str == NULL) printf("NULL CALLOC!!! parameter str\n");
  strcpy(str, QUERY_GOODS_A);
  if(!strcmp(gr, "0"))
    strcat(str, QUERY_GOODS_W_A);
  else
  {
    strcat(str, "= ");
    strcat(str, gr);
  }
  strcat(str, QUERY_GOODS_ORDER);
  switch(sp->order_search_result)
  {
    case 0 :
      strcat(str, ORDERBYCODE);
      break;
    case 1 :
      strcat(str, ORDERBYBARCODE);
      break;
    case 2 :
      strcat(str, ORDERBYTITLE);
      break;
  }

  state = doSQL(myconnection, str); 
  free(str);  
  return state;
}

//==================================================================================//
#define GET_COEFFICIENT "SELECT coefficient FROM ware_barcode WHERE barcode = '"
int Registration::GetBarcodeCoefficient(const char* barcode_str, double & coeff)
{
    
    coeff = 1;
    char * str = (char*) calloc(strlen(GET_COEFFICIENT) + strlen(barcode_str) + 3, sizeof(char));
    
    strcat(str, GET_COEFFICIENT);
    strcat(str, barcode_str);
    strcat(str, "'");
    
    
    int state = doSQL(myconnection, str);
    
    free(str);
    
    if ( state < 0 ) return -1;
    
    if ( PQntuples(result) != 1 ) return -1;
    
    coeff = atof(PQgetvalue(result, 0, 0));
    //printf("coeff = %d \n", coeff);
    
    return 0;
}
	
//==================================================================================//
#define GET_WARE_BY_FILTER "SELECT w.longtitle, w.shortcut, w.price, quantity, wb.barcode, w.internal_id FROM Ware w LEFT JOIN ware_barcode wb ON wb.internal_id = w.internal_id WHERE "
#define GET_WARE_CODE_FILTER " w.internal_id ~~* '%"
#define GET_WARE_BARCODE_FILTER " wb.barcode ~~* '"
#define GET_WARE_TITLE_FILTER " upper(w.longtitle) ~~*  upper('%"
#define GET_WARE_ABSENT_FILTER " w.quantity > 0"
#define GET_WARE_ORDER_BY_CODE " ORDER BY w.internal_id " 
#define GET_WARE_ORDER_BY_BARCODE " ORDER BY wb.barcode " 
#define GET_WARE_ORDER_BY_TITLE " ORDER BY w.longtitle " 
int Registration::VisualSearchByAll( const char* barcode, const char* code, const char* title, bool hide_absent_goods)
{
    /*printf("barcode = %s \n", barcode);
    printf("code = %s \n", code );
    printf("title = %s \n", title);
    
    printf("strlen(bar) = %d \n", strlen(barcode));
    printf("strlen(code) = %d \n", strlen(code));
    printf("strlen(tit) = %d \n", strlen(title));*/
    
    int count_exp = 0;
    int len = strlen(GET_WARE_BY_FILTER);
    if (strlen(barcode) > 0 ) { len += 2*strlen(barcode) + strlen(GET_WARE_BARCODE_FILTER) + strlen("%' ") + 1; count_exp++;  }
    if (strlen(code) > 0 )  {   len += 2*strlen(code) + strlen(GET_WARE_CODE_FILTER) + strlen("%' ") + 1;   count_exp++;  }
    if (strlen(title) > 0 ) {   len += 2*strlen(title) + strlen(GET_WARE_TITLE_FILTER) + strlen("%') ") + 1;  count_exp++;   }
    if ( hide_absent_goods )  {  len += strlen(GET_WARE_ABSENT_FILTER) + 1;   count_exp++;    }
    
    if (sp->order_search_result == 0 ) len += strlen(GET_WARE_ORDER_BY_CODE);
    if (sp->order_search_result == 1 ) len += strlen(GET_WARE_ORDER_BY_BARCODE);
    if (sp->order_search_result == 2 ) len += strlen(GET_WARE_ORDER_BY_TITLE);
    
    if ( count_exp > 1 )  len += (count_exp-1) * strlen(" AND ") ;
    //printf("len = %d \n", len);
	
    
    char* str = (char*) calloc(len +  5, sizeof(char));
    
    strcat(str, GET_WARE_BY_FILTER);
    if (strlen(barcode) > 0 )    { 	
	strcat(str, GET_WARE_BARCODE_FILTER);
	strcat(str, barcode);
	strcat(str, "%' ");
	count_exp--;
	if (count_exp > 0) strcat(str, " AND ");
    }
    
    if (strlen(code) > 0 ) {
	strcat(str, GET_WARE_CODE_FILTER);
	strcat(str, code);
	strcat(str, "%' ");
	count_exp--;
	if (count_exp > 0) strcat(str, " AND ");
    }
    
    if (strlen(title) > 0 ) {
	strcat(str, GET_WARE_TITLE_FILTER);
	strcat(str, title);
	strcat(str, "%') ");
	count_exp--;
	if (count_exp > 0) strcat(str, " AND ");
    }
    
    if ( hide_absent_goods ) {
	strcat(str, GET_WARE_ABSENT_FILTER);
    }
    
    if (sp->order_search_result == 0 ) strcat(str, GET_WARE_ORDER_BY_CODE);
    if (sp->order_search_result == 1 ) strcat(str, GET_WARE_ORDER_BY_BARCODE);
    if (sp->order_search_result == 2 ) strcat(str, GET_WARE_ORDER_BY_TITLE);
    
    //printf("visual search str = %s \n", str);
    
    int state = doSQL(myconnection, str);
    
    free(str);
    
    if ( state < 0 ) return state;
    
    int n = PQntuples(result);
    
    return n;
    
}
//==================================================================================//
#define GET_COUNT_WARE_BY_BARCODE "SELECT internal_id FROM ware_barcode WHERE barcode = '" 
#define GET_COUNT_WARE_BY_CODE "SELECT w.internal_id FROM Ware w LEFT JOIN ware_barcode wb ON wb.internal_id = w.internal_id WHERE  w.internal_id ~~* '%" 
int Registration::GetCountWareByBarcode(const char *barcode, const char * code)
{	
    if ( (strlen(barcode) + strlen(code)) < 1) return 0;
    
    int state = -1;
    
    if (strlen(barcode) > 0 ) {
	char* str = (char *) calloc(strlen(GET_COUNT_WARE_BY_BARCODE) + strlen(barcode) + 2, sizeof(char));
	
	strcpy(str, GET_COUNT_WARE_BY_BARCODE);
	strcat(str, barcode);
	strcat(str, "'");
	state = doSQL(myconnection, str);
	free(str);
    }
    
    if ( strlen(code) > 0 ) {
	char* str = (char *) calloc(strlen(GET_COUNT_WARE_BY_CODE) + strlen(code) + 3, sizeof(char));
	
	strcpy(str, GET_COUNT_WARE_BY_CODE);
	strcat(str, code);
	strcat(str, "%'");
	//printf("str = %s \n", str);
	state = doSQL(myconnection, str);
	free(str);
    }
    
    if ( state < 0 ) return state;
    int n = PQntuples(result);
    PQclear(result);
    return n;
    
}
//==================================================================================//
#define GET_WARE_SHORTCUT "SELECT shortcut FROM ware WHERE internal_id = '"
int Registration::GetWareShortcut(const char* wcode, char* & w_shorcut) {
    
    char str[2000];
    
    //printf("code of ware = %s \n", wcode);
    strcpy(str, GET_WARE_SHORTCUT);
    strcat(str, wcode);
    strcat(str, "'");
    //printf("GetWareShortcut request = %s \n", str);
    
    int state = doSQL(myconnection, str);
    if ( state != 2 ) return -1;
    if ( PQntuples(result) != 1 ) {
	PQclear(result);
	return -1;
    }
    
    //printf("PQgetvalue(result, 0, 0) = %s \n", PQgetvalue(result, 0, 0));
    
    w_shorcut = (char*) calloc(PQgetlength(result, 0,0) + 1, sizeof(char*));
    strcpy(w_shorcut, PQgetvalue(result, 0, 0));
    
    PQclear(result);
    return 0;
}

//==================================================================================//
#define DISCOUNT_GET_VALUE "select * from get_fix_reduction_value(%s, E'%s', %d)"
void Registration::GetDiscountValue(const char *dis_code, const char *ware_code, int pay_type, double &value, int &hd)
{
    int state;
    char *query;

    query = (char *) calloc(strlen(DISCOUNT_GET_VALUE) + 2*strlen(ware_code) + strlen(dis_code) + 21, sizeof(char));
    if (query == NULL) {
        printf("NULL calloc for query\n");
        return;
    }

    char *ware_code_xx = (char *) calloc(2*strlen(ware_code), sizeof(char));
    int error;
    PQescapeStringConn(myconnection, ware_code_xx, ware_code, strlen(ware_code), &error);
    sprintf(query, DISCOUNT_GET_VALUE, dis_code, ware_code_xx, pay_type);
    free(ware_code_xx);

    state = doSQL(myconnection, query);
    free(query);

    if (state != 2) return;

    value = atof(PQgetvalue(result, 0, 0));
    hd = atoi(PQgetvalue(result, 0, 1));

	PQclear(result);
}

//==================================================================================//
